package com.xhorse.lockplatform.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xhorse.lockplatform.comm.constant.ConstantString;
import com.xhorse.lockplatform.comm.constant.FilePathDefine;
import com.xhorse.lockplatform.comm.enums.ResultEnum;
import com.xhorse.lockplatform.comm.exception.LockPlatFormException;
import com.xhorse.lockplatform.comm.util.*;
import com.xhorse.lockplatform.dao.mapper.*;
import com.xhorse.lockplatform.model.*;
import com.xhorse.lockplatform.service.RemoteDataImportService;
import okhttp3.FormBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;

@Service
public class RemoteDataImportServiceImpl implements RemoteDataImportService {

    @Autowired
    private XhKeyMapper xhKeyMapper;

    @Autowired
    private XhImageMapper xhImageMapper;

    @Autowired
    private XhDataMapper xhDataMapper;

    @Autowired
    private XhModelMapper xhModelMapper;

    @Autowired
    private XhBrandMapper xhBrandMapper;

    @Autowired
    private XhUpdateInfoMapper xhUpdateInfoMapper;

    String dbVersion = null;

    @Override
    public void dataImport(int regionId) throws IOException {
        // 2.解压
        String srcPath = FilePathDefine.ZIP_DOWNLOAD_PATH + regionId + ".zip";
        String descDir = FilePathDefine.ZIP_DOWNLOAD_PATH;
        ZipUtil.unZipFiles(new File(srcPath), descDir);
        FileTransport fileTransport = new FileTransport(regionId);
        fileTransport.copy(descDir + regionId,
                FilePathDefine.KEYGENERATE_DATABASE);// 3.复制文件到DataBase文件夹
        XhKeyImport(regionId); // 4.导入XhKey数据
        XhModelImport(regionId); // 4.导入XhModel数据
        XhBrandImport(regionId); // 4.导入XhBrand数据
        XhImageImport(dbVersion); // 4.导入XhImg数据
        XhDataImport(regionId, dbVersion); // 4.导入XhData数据
        updateInfo(regionId); // 导入更新信息
        // 6.删除冗余文件，节约服务器空间
        fileTransport.deleteFile(FilePathDefine.KEYGENERATE_DATABASE + regionId
                + "\\jsonFile");
        fileTransport.deleteFile(FilePathDefine.ZIP_DOWNLOAD_PATH + regionId);
        fileTransport.deleteFile(FilePathDefine.ZIP_DOWNLOAD_PATH + regionId
                + ".zip");
    }

    /**
     * 导入xh_key数据
     */
    public void XhKeyImport(int regionId) {
        String filepath1 = FilePathDefine.KEYGENERATE_DATABASE + regionId
                + "\\jsonFile\\key.json";
        String JsonString = GsonTransferUtil.JsonfileToString(filepath1).trim();
        JSONObject object = JSONObject.parseObject(JsonString);
        List<XhKey> xhKeyList = JSONObject.parseArray(object.getString("list"), XhKey.class);
        dbVersion = xhKeyList.get(0).getVersion();
        LogUtil.getLogger().info("XhKeyImport php Server update key Data: {}", xhKeyList.size());
        // 获取要更新的xhBrand信息
        Map<String, XhBrand> xhBrandList = new HashMap<>();
        for (XhKey xhKey : xhKeyList) {
            generatetype(xhKey);
            XhKey temp = xhKeyMapper.selectKeyInfo(xhKey);
            boolean hasAdd = false;
            if (temp == null) { // 若数据库没有该数据，则新增一条
                xhKeyMapper.insertSelective(xhKey);
                hasAdd = true;
            } else {
                if (!temp.getMd5_all().equals(xhKey.getMd5_all())) { // 若md5相同
                    xhKeyMapper.updateSelective(xhKey); // 更新数据
                    hasAdd = true;
                }
            }
            if (hasAdd) {
                XhModel tempModel = new XhModel();
                tempModel.setModel_id(xhKey.getModel_id());
                tempModel.setLanguage_id(xhKey.getLanguage_id());
                // 添加到brand更新列表
                XhModel xhModel = xhModelMapper.selectModelInfo(tempModel);
                if (xhModel == null) {
                    continue;
                }
                String key = xhModel.getBrand_id() + "_" + xhModel.getLanguage_id();
                if (!xhBrandList.containsKey(key)) {
                    XhBrand xhBrand = new XhBrand();
                    xhBrand.setVersion(dbVersion);
                    xhBrand.setBrand_id(xhModel.getBrand_id());
                    xhBrand.setLanguage_id(xhModel.getLanguage_id());
                    xhBrandList.put(key, xhBrand);
                }
            }
        }
        List<XhBrand> list = new ArrayList<>();
        if (!xhBrandList.isEmpty()) {
            Collection<XhBrand> valCollection = xhBrandList.values();
            list = new ArrayList<>(valCollection);
            // 更新key对应的brand版本信息
            xhBrandMapper.updateBatchByModelId(list);
        }
        LogUtil.getLogger().info("XhKeyImport update Brand Data: {}", list.size());
    }

    /**
     * 导入xh_brand数据
     */
    public void XhBrandImport(int regionId) {
        String filepath1 = FilePathDefine.KEYGENERATE_DATABASE + regionId
                + "\\jsonFile\\brand.json";
        String JsonString = GsonTransferUtil.JsonfileToString(filepath1).trim();
        JSONObject object = JSONObject.parseObject(JsonString);
        List<XhBrand> xhBrandList = JSONObject.parseArray(object.getString("list"), XhBrand.class);
        for (XhBrand xhBrand : xhBrandList) {
            XhBrand temp = xhBrandMapper.selectBrandInfo(xhBrand);
            if (temp == null) { // 若数据库没有该数据，则新增一条
                xhBrandMapper.insertSelective(xhBrand);
            } else {
                if (!temp.getMd5_name().equals(xhBrand.getMd5_name())) { // 若md5相同，则只需要更新状态
                    xhBrandMapper.updateSelective(xhBrand); // 更新数据
                }
            }
        }
    }

    /**
     * 导入xh_model数据
     */
    public void XhModelImport(int regionId) {
        String filepath1 = FilePathDefine.KEYGENERATE_DATABASE + regionId
                + "\\jsonFile\\model.json";
        String JsonString = GsonTransferUtil.JsonfileToString(filepath1).trim();
        JSONObject object = JSONObject.parseObject(JsonString);
        List<XhModel> xhModelList = JSONObject.parseArray(object.getString("list"), XhModel.class);
        // 获取要更新的xhBrand信息
        Map<String, XhBrand> xhBrandList = new HashMap<>();
        for (XhModel xhModel : xhModelList) {
            XhModel temp = xhModelMapper.selectModelInfo(xhModel);
            boolean hasAdd = false;
            if (temp == null) { // 若数据库没有该数据，则新增一条
                xhModelMapper.insertSelective(xhModel);
                hasAdd = true;
            } else {
                if (!temp.getMd5_name().equals(xhModel.getMd5_name())) { // 若md5相同，则只需要更新状态
                    xhModelMapper.updateSelective(xhModel); // 更新数据
                    hasAdd = true;
                }
            }
            if (hasAdd) {
                // 添加到brand更新列表
                String key = xhModel.getBrand_id() + "_" + xhModel.getLanguage_id();
                if (!xhBrandList.containsKey(key)) {
                    XhBrand xhBrand = new XhBrand();
                    xhBrand.setBrand_id(xhModel.getBrand_id());
                    xhBrand.setVersion(dbVersion);
                    xhBrand.setLanguage_id(xhModel.getLanguage_id());
                    xhBrandList.put(key, xhBrand);
                }
            }
        }
        List<XhBrand> list = new ArrayList<>();
        if (!xhBrandList.isEmpty()) {
            Collection<XhBrand> valCollection = xhBrandList.values();
            list = new ArrayList<>(valCollection);
            // 更新key对应的brand版本信息
            xhBrandMapper.updateBatchByModelId(list);
        }
        LogUtil.getLogger().info("XhModelImport update Brand Data: {}", list.size());
    }

    /**
     * 对XhKey的type字段生成数据
     *
     * @param xhKey
     */
    public void generatetype(XhKey xhKey) {
        char[] bytearry = new char[32];
        bytearry[0] = '0';
        for (int i = 0; i < 26; i++) {
            bytearry[i] = '0';
        }
        if (xhKey.getEncode().equals("FSK")) {
            bytearry[30] = '0';
            bytearry[31] = '1';
        } else {
            bytearry[30] = '0';
            bytearry[31] = '0';
        }
        if (xhKey.getType_name().startsWith("X/XN")) {
            bytearry[28] = '1';
            bytearry[29] = '1';
        } else if (xhKey.getType_name().startsWith("XN")) {
            bytearry[28] = '0';
            bytearry[29] = '1';
        } else {
            bytearry[28] = '0';
            bytearry[29] = '0';
        }
        if (xhKey.getCloneable_remote() != null) {
            if (xhKey.getCloneable_remote().equals("1")) {
                bytearry[27] = '1';
            } else if (!xhKey.getCloneable_remote().equals("1")) {
                bytearry[27] = '0';
            }
        } else {
            bytearry[27] = '0';
        }
        if (xhKey.getCloneable_chip() != null) {
            if (xhKey.getCloneable_chip().equals("1")) {
                bytearry[26] = '1';
            } else if (!xhKey.getCloneable_chip().equals("1")
                    || xhKey.getCloneable_chip() == null) {
                bytearry[26] = '0';
            }
        } else {
            bytearry[26] = '0';
        }
        String bitstr = String.valueOf(bytearry);
        int temp = Integer.valueOf(bitstr, 2);
        String type = Integer.toHexString(temp);
        if (type.length() == 1) {
            type = "0000000" + type;
        } else if (type.length() == 2) {
            type = "000000" + type;
        }
        xhKey.setType(type);
    }

    /**
     * XhImage库导入
     */
    public void XhImageImport(String dbVersion) {
        // 导入车钥匙图片
        ImgImport(FilePathDefine.KEYGENERATE_DATABASE + "image\\keyImg", 2,
                dbVersion);
        // 导入品牌图片
        ImgImport(FilePathDefine.KEYGENERATE_DATABASE + "image\\brandImg", 1,
                dbVersion);
    }

    public void ImgImport(String srcPath, int typeId, String dbversion) {

        File srcFile = new File(srcPath);
        File[] srcFileArray = srcFile.listFiles();
        for (File file : srcFileArray) {
            Long filelength = file.length();
            byte[] Content = new byte[filelength.intValue()];
            fileDataRead(file, Content);
            XhImage xhImage = new XhImage(); // 初始化一个数据对象
            String md5String = DecriptUtil.BytesMD5(Content); // 获取图片md5值
            String imgidstr = file.getName();
            int imgId = Integer.valueOf(imgidstr.replace(".png", "").replace(
                    ".jpg", ""));
            xhImage.setMd5Img(md5String);// 设置图片MD5值
            xhImage.setImgId(imgId); // 设置图片id
            xhImage.setImgUrl(file.getAbsolutePath().replace(
                    FilePathDefine.KEYGENERATE_DATABASE, "")); // 设置图片路径
            xhImage.setTypeId(typeId); // 设置图片类型
            xhImage.setVersion(dbversion); // 设置图片版本
            String originalMD5 = xhImageMapper.selectImgMd5ById(imgId, typeId);
            if (originalMD5 == null) { // 若没有，则插入
                xhImageMapper.insertSelective(xhImage);
            } else {
                if (!md5String.equals(originalMD5)) {
                    xhImageMapper.updateMD5Selective(xhImage); // 若MD5不相同，则更新MD5
                }
            }
        }
    }

    /**
     * 获取bin\hex文件
     *
     * @param regionId
     * @param dbversion
     */
    public void XhDataImport(int regionId, String dbversion) {
        String binDirect = FilePathDefine.KEYGENERATE_DATABASE + regionId + "\\binFile";
        String hexDirct = FilePathDefine.KEYGENERATE_DATABASE + regionId + "\\hexFile";
        FileDataImport(binDirect, regionId, dbversion, 1);
        FileDataImport(hexDirct, regionId, dbversion, 2);
    }

    public void FileDataImport(String srcPath, int regionId, String dbversion,
                               int typeId) {
        File srcDirect = new File(srcPath);
        File[] fileArray = srcDirect.listFiles();
        for (File file : fileArray) {
            Long binlength = file.length();
            byte[] binContent = new byte[binlength.intValue()];
            fileDataRead(file, binContent);
            XhData xhData = new XhData(); // 初始化一个数据对象
            String md5String = DecriptUtil.BytesMD5(binContent); // 获取图片md5值
            String imgidstr = file.getName();
            int fileId = Integer.valueOf(imgidstr);
            if (typeId == 1) {
                xhData.setMd5Bin(md5String);// 设置图片MD5值
                xhData.setBinUrl(file.getAbsolutePath().replace(
                        FilePathDefine.KEYGENERATE_DATABASE, "")); // 设置bin文件MD5
            } else {
                xhData.setMd5Hex(md5String);// 设置图片MD5值
                xhData.setHexUrl(file.getAbsolutePath().replace(
                        FilePathDefine.KEYGENERATE_DATABASE, "")); // 设置hex文件MD5
            }
            xhData.setFileId(fileId); // 设置图片id
            xhData.setRegionId(regionId); // 设置数据所属地区id
            xhData.setVersion(dbversion); // 设置文件版本
            XhData temp = xhDataMapper.selectDataInfo(xhData);
            if (temp == null) {
                xhDataMapper.insertSelective(xhData); // 若数据库没有该ID对应的记录，则新增一条
                continue;
            }
            boolean hasUpdate;
            if (typeId == 1) {
                hasUpdate = !temp.getMd5Bin().equals(xhData.getMd5Bin());
            } else {
                hasUpdate = !md5String.equals(xhData);
            }
            if (hasUpdate) {
                xhDataMapper.updateMD5Selective(xhData); // 若MD5不相同，则更新MD5
            }
        }
    }

    /**
     * 读公共方法
     *
     * @param file
     * @param binContent
     */
    private void fileDataRead(File file, byte[] binContent) {
        try {
            FileInputStream fis = new FileInputStream(file);
            fis.read(binContent);
            fis.close();
        } catch (FileNotFoundException e) {
            throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "找不到对应文件[" + file.getPath() + "]");
        } catch (IOException e) {
            throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "文件流操作,遇到异常", e);
        }
    }

    /**
     * 将数据文件中的文件转到压缩目录当中
     */
    @Override
    public void zipAllGenerate(int regionId, String dbversion) {
        GenerateImgFile imgFile = new GenerateImgFile(dbversion, regionId);
        GenerateDataFile dataFile = new GenerateDataFile(dbversion, regionId);
        Thread imgThread = new Thread(imgFile);
        Thread dataThread = new Thread(dataFile);
        imgThread.start();
        dataThread.start();
        try { // 将主线程阻塞住，待这个耗时操作完成后再生成zip文件
            imgThread.join();
            dataThread.join();
        } catch (InterruptedException e) {
            throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "文件处理,遇到异常", e);
        }
        // 生成压缩包
        String binPath = FilePathDefine.KEYGENERATE + regionId + "\\binFile";
        String hexPath = FilePathDefine.KEYGENERATE + regionId + "\\hexFile";
        String keyImgPath = FilePathDefine.KEYGENERATE + regionId + "\\keyImg";
        String brandImgPath = FilePathDefine.KEYGENERATE + regionId + "\\brandImg";
        String zipPath = FilePathDefine.KEYGENERATE + regionId + ".zip";
        ZipUtil zipUtil = new ZipUtil(zipPath);
        zipUtil.compress(binPath, hexPath, keyImgPath, brandImgPath);
        FileTransport fileTransport = new FileTransport();
        fileTransport.deleteFile(FilePathDefine.KEYGENERATE + regionId);
    }

    // 获取图片文件的线程
    private class GenerateImgFile implements Runnable {
        String dbversion;
        int regionId;

        public GenerateImgFile(String dbversion, int regionId) {
            super();
            this.dbversion = dbversion;
            this.regionId = regionId;
        }

        @Override
        public void run() {
            // 判断文件夹是否存在，不存在，则新建
            File brandDir = new File(FilePathDefine.KEYGENERATE + regionId
                    + "\\brandImg");
            File keyDir = new File(FilePathDefine.KEYGENERATE + regionId
                    + "\\keyImg");
            if (!brandDir.exists()) {
                brandDir.mkdirs();
            }
            if (!keyDir.exists()) {
                keyDir.mkdirs();
            }
            // 获取文件路径
            List<XhImage> xhImages = xhImageMapper.selectDir(dbversion,
                    regionId);
            //xhImages.addAll(xhImageMapper.selectChipImg());
            byte[] bArray = new byte[8];
            for (XhImage xhImage : xhImages) {
                // 随机产生八位字节数组
                Random random = new Random();
                random.nextBytes(bArray);
                // 复制文件
                File imgFile = new File(FilePathDefine.KEYGENERATE_DATABASE
                        + xhImage.getImgUrl());
                if (imgFile.exists() && imgFile.length() != 0) {
                    if (xhImage.getTypeId() == 1) {
                        fileWriteComm(imgFile, FilePathDefine.KEYGENERATE_DATABASE + xhImage.getImgUrl(),
                                brandDir.getPath() + "\\" + xhImage.getImgId());
                    } else {
                        fileWriteComm(imgFile, FilePathDefine.KEYGENERATE_DATABASE + xhImage.getImgUrl(),
                                keyDir.getPath() + "\\" + xhImage.getImgId());
                    }
                } else {
                    continue;
                }

            }
        }

    }

    // 获取bin\hex文件的线程
    private class GenerateDataFile implements Runnable {

        String dbversion;
        int regionId;

        public GenerateDataFile(String dbversion, int regionId) {
            super();
            this.dbversion = dbversion;
            this.regionId = regionId;
        }

        @Override
        public void run() {
            // 判断文件夹是否存在，不存在，则新建
            File binDir = new File(FilePathDefine.KEYGENERATE + regionId
                    + "\\binFile");
            File hexDir = new File(FilePathDefine.KEYGENERATE + regionId
                    + "\\hexFile");
            if (!binDir.exists()) {
                binDir.mkdirs();
            }
            if (!hexDir.exists()) {
                hexDir.mkdirs();
            }
            // 获取文件路径
            List<XhData> xhDatas = xhDataMapper.selectDir(dbversion, regionId);
            for (XhData xhData : xhDatas) {

                fileWriteComm(null, FilePathDefine.KEYGENERATE_DATABASE + xhData.getBinUrl(),
                        binDir.getPath() + "\\" + xhData.getFileId());
                fileWriteComm(null, FilePathDefine.KEYGENERATE_DATABASE + xhData.getHexUrl(),
                        hexDir.getPath() + "\\" + xhData.getFileId());
            }
        }
    }

    // 文件写入公共方法
    private void fileWriteComm(File file, String FileUrl, String path) {
        int index;
        try {
            if (file == null) {
                file = new File(FileUrl);
            }
            if (file.exists()) {
                FileInputStream fis = new FileInputStream(file);
                byte[] buffer = new byte[1024];
                FileOutputStream fos = new FileOutputStream(path);
                while ((index = fis.read(buffer)) != -1) {
                    fos.write(buffer, 0, index);
                }
                fis.close();
                fos.close();
            }
        } catch (FileNotFoundException e) {
            throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "找不到对应文件[" + FileUrl + "]");
        } catch (IOException e) {
            throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "文件流操作,遇到异常", e);
        }
    }

    @Override
    public void updateInfo(int regionId) {
        try {
            RequestBody requestBody = new FormBody.Builder().add("region_id",
                    regionId + "").add("cmd", "21").build();
            Request request = new Request.Builder()
                    .url(ConstantString.PHP_URL_DATATRANSFER)
                    .post(requestBody).build();
            HttpClientUtil httpClientUtil = HttpClientUtil.getInstance();
            Response response = httpClientUtil.getClient().newCall(request)
                    .execute();
            String result = String.valueOf(response.body());
            JSONObject object = JSONObject.parseObject(result);
            XhUpdateInfo xhUpdateInfo = new XhUpdateInfo();
            xhUpdateInfo.setVersion(object.getString("version"));
            xhUpdateInfo.setEditionTime(DateUtils.nowDateString(DateUtils.DATE_PATTERN));
            xhUpdateInfo.setRegionId(regionId);
            xhUpdateInfo.setLanguageId(2);
            String strCh = object.getString("ch");
            String strEn = object.getString("en");
            if (StringUtil.isNotNil(strEn)) {
                xhUpdateInfo.setContent(strCh);
                if (StringUtil.isChineseStr(strCh)) {
                    xhUpdateInfo.setLanguageId(1);
                }
                xhUpdateInfoMapper.insertSelective(xhUpdateInfo);
            }
            if (StringUtil.isNotNil(strCh)) {
                xhUpdateInfo.setContent(strEn);
                xhUpdateInfoMapper.insertSelective(xhUpdateInfo);
            }
        } catch (IOException e) {
            throw new LockPlatFormException(ResultEnum.FAILED.getCode(), "更新区域[" + regionId + "]包信息时，遇到异常", e);
        }
    }

}
